﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;

namespace DomainDriver.DomainModeling.DataProviders
{
    public class DataProvider : IDataProvider
    {
        private DataSourcePersistenceType m_PersistenceType;
        private Type m_RequiredDataSourceType;
        private object m_UntypedDataSource;
        protected bool m_IsPerformingBatchChanges;

        public DataProvider(DataSourcePersistenceType persistenceType, Type requiredDataSourceType, object dataSource)
        {
            m_PersistenceType = persistenceType;
            m_RequiredDataSourceType = requiredDataSourceType;
            m_IsPerformingBatchChanges = false;

            if (DataSourceType == null)
            { throw new ApplicationException(); }

            if (dataSource != null)
            {
                if (!DataSourceType.IsInstanceOfType(dataSource))
                {
                    throw new ApplicationException();
                }
            }


            m_UntypedDataSource = dataSource;
        }

        public DataProvider(DataSourcePersistenceType persistenceType, Type requiredDataSourceType)
            : this(persistenceType, requiredDataSourceType, null)
        {
            // do nothing
        }

        public DataSourcePersistenceType PersistenceType
        {
            get { return m_PersistenceType; }
        }

        public Type DataSourceType
        {
            get { return m_RequiredDataSourceType; }
        }

        public object DataSource
        {
            get
            {
                return m_UntypedDataSource;
            }
            set
            {
                if (value != null)
                {
                    if (!DataSourceType.IsInstanceOfType(value))
                    {
                        throw new ApplicationException();
                    }
                }

                m_UntypedDataSource = value;
            }
        }

        public DATASOURCE GetTypedDataSource<DATASOURCE>()
            where DATASOURCE : class
        {
            return (DataSource as DATASOURCE);
        }

        public virtual bool SupportsBatchChanges
        {
            get
            {
                if (DataSource is DbContext)
                { return true; }
                return false;
            }
        }

        public virtual bool IsPerformingBatchChanges
        {
            get { return m_IsPerformingBatchChanges; }
        }

        public virtual void BeginBatchChangeSet()
        {
            if (DataSource is DbContext)
            {
                if (m_IsPerformingBatchChanges)
                { throw new InvalidOperationException("A Batch Change Set has already been started."); }
                m_IsPerformingBatchChanges = true;
            }
            else
            { /* This is a no-op */ }
        }

        public virtual void CompleteBatchChangeSet()
        {
            if (DataSource is DbContext)
            {
                if (!m_IsPerformingBatchChanges)
                { throw new InvalidOperationException("A Batch Change Set has not yet been started."); }
                m_IsPerformingBatchChanges = false;
                ((DbContext)DataSource).SaveChanges();
            }
            else
            { /* This is a no-op */ }
        }
    }
}